home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr05 / xnot12a.zip / RANDOM.C < prev    next >
C/C++ Source or Header  |  1993-05-20  |  16KB  |  724 lines

  1. #include "jam.h"
  2. /*
  3.  *        Assorted commands.
  4.  * The file contains the command
  5.  * processors for a large assortment of unrelated
  6.  * commands. The only thing they have in common is
  7.  * that they are all command processors.
  8.  *
  9.  * I mucked with this code to begin to support GNU-like 
  10.  * indenting for C code. It isn't done...
  11.  *
  12.  */
  13. #include "stdio.h"
  14. #include  "def.h"
  15. #include "key.h"
  16.  
  17. static BOOL rn_(performindent,(int n, LINE *lp));
  18.  
  19. static BOOL usetab = TRUE;  /* for performindent */
  20. static BOOL doCindent = FALSE;
  21.  
  22. int CindentOn(f, n)
  23. int f, n;
  24. {
  25. #ifdef INDENTING
  26.   doCindent = TRUE;
  27. #endif
  28.   return (TRUE);
  29. }
  30. int CindentOff(f, n)
  31. int f, n;
  32. {
  33. #ifdef INDENTING
  34.   doCindent = FALSE;
  35. #endif
  36.   return (TRUE);
  37. }
  38. BOOL isCindent()
  39. {
  40.   return (doCindent);
  41. }
  42.  
  43. /* Work function to indent an existing line - doto must
  44. * be set correctly by caller, buffer is always curbp
  45. */
  46. static BOOL performindent(n, lp)
  47. int n;
  48. LINE *lp;
  49. {
  50.   int i;
  51.  
  52.   if (!usetab || (curbp->b_flag & BFNOTAB))
  53.      return(linsert(n, ' '));
  54.  
  55.   if ((i = n/TABSTOP) != 0)
  56.      if (!linsert(i, '\t'))
  57.         return(FALSE);
  58.  
  59.   if ((i = n%TABSTOP) != 0)
  60.      return(linsert(i, ' '));
  61.  
  62.   return(TRUE);
  63. }
  64.  
  65. /*
  66.  * Display a bunch of useful information about
  67.  * the current location of dot. The character under the
  68.  * cursor (in octal), the current line, row, and column, and
  69.  * approximate position of the cursor in the file (as a percentage)
  70.  * is displayed. The column position assumes an infinite position
  71.  * display; it does not truncate just because the screen does.
  72.  * This is normally bound to "C-X =".
  73.  */
  74. /*ARGSUSED*/
  75. showcpos(f, n)
  76. int f, n;
  77. {
  78.   char buf[512];
  79.  
  80.   calccpos(buf, FALSE);
  81.   ewprintf(buf);
  82.   return(TRUE);
  83. }
  84.  
  85. showline(f, n)
  86. int f, n;
  87. {
  88.   char buf[512];
  89.  
  90.   calccpos(buf, TRUE);
  91.   ewprintf(buf);
  92.   return(TRUE);
  93. }
  94.  
  95. /* do work of constructing cpos string - broken from showcpos (JAM)
  96. */
  97. void calccpos(buf, shortflg)
  98. char *buf;
  99. int shortflg;
  100. {
  101.     register LINE    *clp;
  102.     register long    nchar;
  103.     long        cchar;
  104.     register int    nline, row;
  105.     int        cline, cbyte;    /* Current line/char/byte */
  106.     int        ratio;
  107.         int             cratio = '%';
  108.  
  109.     clp = lforw(curbp->b_linep);        /* Collect the data.    */
  110.     nchar = 0;
  111.     nline = 0;
  112.     for (;;) {
  113.         ++nline;            /* Count this line    */
  114.         if (clp == curwp->w_dotp) {
  115.             cline = nline;        /* Mark line        */
  116.             cchar = nchar + curwp->w_doto;
  117.             if (curwp->w_doto == llength(clp))
  118.                 cbyte = '\n';
  119.             else
  120.                 cbyte = lgetc(clp, curwp->w_doto);
  121.         }
  122.         nchar += llength(clp);        /* Now count the chars    */
  123.         clp = lforw(clp);
  124.         if (clp == curbp->b_linep) break;
  125.         nchar++;            /* count the newline    */
  126.     }
  127.     row = curwp->w_toprow + 1;        /* Determine row.    */
  128.     clp = curwp->w_linep;
  129.     while (clp!=curbp->b_linep && clp!=curwp->w_dotp) {
  130.         ++row;
  131.         clp = lforw(clp);
  132.     }
  133.     /*NOSTRICT*/
  134.     ratio = (int)(nchar ? (100L*cchar) / nchar : 100); 
  135.     if (!shortflg)
  136.       sprintf(buf, 
  137.         "Char: %c (0%o)  point=%ld(%d%c) line=%d  row=%d  col=%d",
  138.         cbyte, cbyte, cchar, ratio, cratio, cline, row, getcolpos());
  139.     else
  140.       sprintf(buf, "Line %d Col %d (%d%c)", 
  141.                   cline, getcolpos(), ratio, cratio);
  142. }
  143.  
  144. int getcolpos() 
  145. {
  146.     register int    col, i, c;
  147.  
  148.     col = 1;                /* Determine column.    */
  149.     for (i=0; i<curwp->w_doto; ++i) {
  150.         c = lgetc(curwp->w_dotp, i);
  151.         if (c == '\t') 
  152.            {
  153.             col |= 0x07;
  154.             ++col;
  155.            } else if (ISCTRL(c) != FALSE)
  156.             ++col;
  157.         ++col;
  158.     }
  159.     return col;
  160. }
  161. /*
  162.  * Twiddle the two characters on either side of
  163.  * dot. If dot is at the end of the line twiddle the
  164.  * two characters before it. Return with an error if dot
  165.  * is at the beginning of line; it seems to be a bit
  166.  * pointless to make this work. This fixes up a very
  167.  * common typo with a single stroke. Normally bound
  168.  * to "C-T". This always works within a line, so
  169.  * "WFEDIT" is good enough.
  170.  */
  171. /*ARGSUSED*/
  172. twiddle(f, n)
  173. int f, n;
  174. {
  175.     register LINE    *dotp;
  176.     register int    doto;
  177.     register int    cr;
  178.  
  179.   if (curbp->b_flag & BFVIEW)
  180.     {
  181.       ttbeep();
  182.       return FALSE;
  183.     }
  184.   if (filetimechanged(curbp))
  185.     return(FALSE);
  186.   clearUndo(curbp);
  187.   cacheTwiddle();
  188.  
  189.     dotp = curwp->w_dotp;
  190.     doto = curwp->w_doto;
  191.     if(doto==llength(dotp)) {
  192.         if(--doto<=0) return FALSE;
  193.     } else {
  194.         if(doto==0) 
  195.                   return FALSE;
  196.         ++curwp->w_doto;
  197.     }
  198.     cr = lgetc(dotp, doto--);
  199.     lchange(WFEDIT);
  200.         changelineflag(dotp, TRUE);
  201.     lputc(dotp, doto+1, lgetc(dotp, doto));
  202.     lputc(dotp, doto, (char)cr);
  203.     return TRUE;
  204. }
  205.  
  206. /*
  207.  * Open up some blank space. The basic plan
  208.  * is to insert a bunch of newlines, and then back
  209.  * up over them. Everything is done by the subcommand
  210.  * procerssors. They even handle the looping. Normally
  211.  * this is bound to "C-O".
  212.  */
  213. /*ARGSUSED*/
  214. openline(f, n)
  215. int f, n;
  216. {
  217.     register int    i;
  218.     register int    s;
  219.  
  220.   if (curbp->b_flag & BFVIEW)
  221.     {
  222.       ttbeep();
  223.       return FALSE;
  224.     }
  225.   if (filetimechanged(curbp))
  226.     return(FALSE);
  227.   clearUndo(curbp);
  228.   cacheInsert((RSIZE)n);
  229.  
  230.     if (n < 0)
  231.         return FALSE;
  232.     if (n == 0)
  233.         return TRUE;
  234.     i = n;                    /* Insert newlines.    */
  235.     do {
  236.         s = lnewline();
  237.     } while (s==TRUE && --i);
  238.     if (s == TRUE)                /* Then back up overtop */
  239.         s = backchar(f | FFRAND, n);    /* of them all.        */
  240.     return s;
  241. }
  242.  
  243. /*
  244.  * Insert a newline.
  245.  * If you are at the end of the line and the
  246.  * next line is a blank line, just move into the
  247.  * blank line. This makes "C-O" and "C-X C-O" work
  248.  * nicely, and reduces the ammount of screen
  249.  * update that has to be done. This would not be
  250.  * as critical if screen update were a lot
  251.  * more efficient.
  252.  */
  253. /*ARGSUSED*/
  254. newline(f, n)
  255. int f, n;
  256. {
  257.     register LINE    *lp;
  258.     register int    s;
  259.  
  260.   if (curbp->b_flag & BFVIEW)
  261.     {
  262.       ttbeep();
  263.       return FALSE;
  264.     }
  265.   if (filetimechanged(curbp))
  266.     return(FALSE);
  267.   clearUndo(curbp);
  268.  
  269.     if (n < 0) return FALSE;
  270.     while (n--) {
  271.         lp = curwp->w_dotp;
  272.         if (llength(lp) == curwp->w_doto
  273.         && lforw(lp) != curbp->b_linep
  274.         && llength(lforw(lp)) == 0) {
  275.             if ((s=forwchar(FFRAND, 1)) != TRUE)
  276.                 return s;
  277.         } else if ((s=lnewline()) != TRUE)
  278.             return s;
  279.     }
  280.     return TRUE;
  281. }
  282.  
  283. /*
  284.  * Delete blank lines around dot.
  285.  * What this command does depends if dot is
  286.  * sitting on a blank line. If dot is sitting on a
  287.  * blank line, this command deletes all the blank lines
  288.  * above and below the current line. If it is sitting
  289.  * on a non blank line then it deletes all of the
  290.  * blank lines after the line. Normally this command
  291.  * is bound to "C-X C-O". Any argument is ignored.
  292.  */
  293. /*ARGSUSED*/
  294. deblank(f, n)
  295. int f, n;
  296. {
  297.     register LINE    *lp1;
  298.     register LINE    *lp2;
  299.     register RSIZE    nld;
  300.  
  301.   if (curbp->b_flag & BFVIEW)
  302.     {
  303.       ttbeep();
  304.       return FALSE;
  305.     }
  306.   if (filetimechanged(curbp))
  307.     return(FALSE);
  308.   clearUndo(curbp);
  309.  
  310.     lp1 = curwp->w_dotp;
  311.         changelineflag(lp1, TRUE);
  312.     while (llength(lp1)==0 && (lp2=lback(lp1))!=curbp->b_linep)
  313.         lp1 = lp2;
  314.     lp2 = lp1;
  315.     nld = (RSIZE) 0;
  316.     while ((lp2=lforw(lp2))!=curbp->b_linep && llength(lp2)==0)
  317.         ++nld;
  318.     if (nld == 0)
  319.         return (TRUE);
  320.     curwp->w_dotp = lforw(lp1);
  321.     curwp->w_doto = 0;
  322.     return ldelete((RSIZE)nld, KNONE);
  323. }
  324.  
  325. /*
  326.  * Delete any whitespace around dot, then insert a space.
  327.  */
  328. justone(f, n) 
  329. int f, n;
  330. {
  331.   if (curbp->b_flag & BFVIEW)
  332.     {
  333.       ttbeep();
  334.       return FALSE;
  335.     }
  336.   if (filetimechanged(curbp))
  337.     return(FALSE);
  338.   clearUndo(curbp);
  339.  
  340.   (VOID) delwhite(f, n);
  341.   return linsert(1, ' ');
  342. }
  343. /*
  344.  * Delete any whitespace around dot.
  345.  */
  346. /*ARGSUSED*/
  347. delwhite(f, n)
  348. int f, n;
  349. {
  350.     register int    col, c, s;
  351.  
  352.   if (curbp->b_flag & BFVIEW)
  353.     {
  354.       ttbeep();
  355.       return FALSE;
  356.     }
  357.   if (filetimechanged(curbp))
  358.     return(FALSE);
  359.   clearUndo(curbp);
  360.  
  361.   col = curwp->w_doto;
  362.   while (((c = lgetc(curwp->w_dotp, col)) == ' ' || c == '\t')
  363.      && col < llength(curwp->w_dotp))
  364.     ++col;
  365.     
  366.   do {
  367.     if (curwp->w_doto == 0) {
  368.       s = FALSE;
  369.       break;
  370.       }
  371.     if ((s = backchar(FFRAND, 1)) != TRUE) 
  372.       break;
  373.     } while ((c = lgetc(curwp->w_dotp, curwp->w_doto)) == ' ' || c == '\t');
  374.  
  375.   if (s == TRUE) 
  376.     (VOID) forwchar(FFRAND, 1);
  377.  
  378.   (VOID) ldelete((RSIZE)(col - curwp->w_doto), KNONE);
  379.   return TRUE;
  380. }
  381. /* 
  382.  * Insert a newline, then enough
  383.  * tabs and spaces to duplicate the indentation
  384.  * of the previous line. Assumes tabs are every eight
  385.  * characters. Quite simple. Figure out the indentation
  386.  * of the current line. Insert a newline by calling
  387.  * the standard routine. Insert the indentation by
  388.  * inserting the right number of tabs and spaces.
  389.  * Return TRUE if all ok. Return FALSE if one
  390.  * of the subcomands failed. Normally bound
  391.  * to "C-J".
  392.  */
  393. /*ARGSUSED*/
  394. indent(f, n)
  395. int f, n;
  396. {
  397.     register int    nicol;
  398.  
  399.   if (curbp->b_flag & BFVIEW)
  400.     {
  401.       ttbeep();
  402.       return FALSE;
  403.     }
  404.   if (filetimechanged(curbp))
  405.     return(FALSE);
  406.   clearUndo(curbp);
  407.  
  408.  
  409.   if (n < 0) 
  410.     return (FALSE);
  411.   nicol = indentofline(n, curwp->w_dotp); 
  412.   if (lnewline() == FALSE)
  413.     return(FALSE);
  414.   return(performindent(nicol, curwp->w_dotp));   
  415. }
  416.  
  417. /*
  418.  * Delete forward. This is real
  419.  * easy, because the basic delete routine does
  420.  * all of the work. Watches for negative arguments,
  421.  * and does the right thing. If any argument is
  422.  * present, it kills rather than deletes, to prevent
  423.  * loss of text if typed with a big argument.
  424.  * Normally bound to "C-D".
  425.  */
  426. /*ARGSUSED*/
  427. forwdel(f, n)
  428. int f, n;
  429. {
  430.   if (curbp->b_flag & BFVIEW)
  431.     {
  432.       ttbeep();
  433.       return FALSE;
  434.     }
  435.   if (filetimechanged(curbp))
  436.     return(FALSE);
  437.  
  438.   if (!(lastflag & CFKILL))
  439.     {
  440.       clearUndo(curbp);
  441.       cacheKill();
  442.     }
  443.     if (n < 0)
  444.         return backdel(f | FFRAND, -n);
  445.     if (f & FFARG) {            /* Really a kill.    */
  446.         if ((lastflag&CFKILL) == 0)
  447.             kdelete();
  448.         thisflag |= CFKILL;
  449.     }
  450.     return ldelete((RSIZE) n, (f & FFARG) ? KFORW : KNONE);
  451. }
  452.  
  453. /*
  454.  * Delete backwards. This is quite easy too,
  455.  * because it's all done with other functions. Just
  456.  * move the cursor back, and delete forwards.
  457.  * Like delete forward, this actually does a kill
  458.  * if presented with an argument.
  459.  */
  460. /*ARGSUSED*/
  461. backdel(f, n)
  462. int f, n;
  463. {
  464.     register int    s;
  465.  
  466.   if (curbp->b_flag & BFVIEW)
  467.     {
  468.       ttbeep();
  469.       return FALSE;
  470.     }
  471.   if (filetimechanged(curbp))
  472.     return(FALSE);
  473.   if (!(lastflag & CFKILL))
  474.     {
  475.       clearUndo(curbp);
  476.       cacheKill();
  477.     }
  478.  
  479.     if (n < 0)
  480.         return forwdel(f | FFRAND, -n);
  481.     if (f & FFARG) {            /* Really a kill.    */
  482.         if ((lastflag&CFKILL) == 0)
  483.             kdelete();
  484.         thisflag |= CFKILL;
  485.     }
  486.     if ((s=backchar(f | FFRAND, n)) == TRUE)
  487.         s = ldelete((RSIZE) n, (f & FFARG) ? KFORW : KNONE);
  488.     return s;
  489. }
  490.  
  491. /*
  492.  * Kill line. If called without an argument,
  493.  * it kills from dot to the end of the line, unless it
  494.  * is at the end of the line, when it kills the newline.
  495.  * If called with an argument of 0, it kills from the
  496.  * start of the line to dot. If called with a positive
  497.  * argument, it kills from dot forward over that number
  498.  * of newlines. If called with a negative argument it
  499.  * kills any text before dot on the current line,
  500.  * then it kills back abs(arg) lines.
  501.  */
  502. /*ARGSUSED*/
  503. killline(f, n) 
  504. int f, n;
  505. {
  506.     register RSIZE    chunk;
  507.     register LINE    *nextp;
  508.     register int    i, c;
  509.     VOID     kdelete();
  510.  
  511.   if (curbp->b_flag & BFVIEW)
  512.     {
  513.       ttbeep();
  514.       return FALSE;
  515.     }
  516.   if (filetimechanged(curbp))
  517.     return(FALSE);
  518.   if (!(lastflag & CFKILL))
  519.     {
  520.       clearUndo(curbp);
  521.       cacheKill();
  522.     }
  523.  
  524.     if ((lastflag&CFKILL) == 0)        /* Clear kill buffer if */
  525.       kdelete();            /* last wasn't a kill.    */
  526.     thisflag |= CFKILL;
  527.     if (!(f & FFARG)) {
  528.       for (i = curwp->w_doto; i < llength(curwp->w_dotp); ++i)
  529.         if ((c = lgetc(curwp->w_dotp, i)) != ' ' && c != '\t')
  530.           break;
  531.       if (i == llength(curwp->w_dotp))
  532.         chunk = llength(curwp->w_dotp)-curwp->w_doto + 1;
  533.       else {
  534.         chunk = llength(curwp->w_dotp)-curwp->w_doto;
  535.         if (chunk == 0)
  536.           chunk = 1;
  537.       }
  538.     } else if (n > 0) {
  539.         chunk = llength(curwp->w_dotp)-curwp->w_doto+1;
  540.         nextp = lforw(curwp->w_dotp);
  541.         i = n;
  542.         while (--i) {
  543.             if (nextp == curbp->b_linep)
  544.                 break;
  545.             chunk += llength(nextp)+1;
  546.             nextp = lforw(nextp);
  547.         }
  548.     } else {                /* n <= 0        */
  549.         chunk = curwp->w_doto;
  550.         curwp->w_doto = 0;
  551.         i = n;
  552.         while (i++) {
  553.             if (lback(curwp->w_dotp) == curbp->b_linep)
  554.                 break;
  555.             curwp->w_dotp = lback(curwp->w_dotp);
  556.             curwp->w_flag |= WFMOVE;
  557.             chunk += llength(curwp->w_dotp)+1;
  558.         }
  559.     }
  560.     /*
  561.      * KFORW here is a bug. Should be KBACK/KFORW, but we need to
  562.      * rewrite the ldelete code (later)?
  563.      */
  564.     return (ldelete(chunk,    KFORW));
  565. }
  566.  
  567. /*
  568.  * Yank text back from the kill buffer. This
  569.  * is really easy. All of the work is done by the
  570.  * standard insert routines. All you do is run the loop,
  571.  * and check for errors. The blank
  572.  * lines are inserted with a call to "newline"
  573.  * instead of a call to "lnewline" so that the magic
  574.  * stuff that happens when you type a carriage
  575.  * return also happens when a carriage return is
  576.  * yanked back from the kill buffer.
  577.  * An attempt has been made to fix the cosmetic bug
  578.  * associated with a yank when dot is on the top line of
  579.  * the window (nothing moves, because all of the new
  580.  * text landed off screen).
  581.  */
  582. /*ARGSUSED*/
  583. yank(f, n)
  584. int f, n;
  585. {
  586.     register int    c;
  587.     register int    i;
  588.     register LINE    *lp;
  589.     register int    nline;
  590.     VOID     isetmark();
  591.  
  592.  
  593.   if (curbp->b_flag & BFVIEW)
  594.     {
  595.       ttbeep();
  596.       return FALSE;
  597.     }
  598.   if (filetimechanged(curbp))
  599.     return(FALSE);
  600.   clearUndo(curbp);
  601.   cacheInsert(return_kused());
  602.  
  603.     if (n < 0) 
  604.       return FALSE;
  605.     nline = 0;                /* Newline counting.    */
  606.     while (n--) {
  607.         isetmark();            /* mark around last yank */
  608.         i = 0;
  609.         while ((c=kremove(i)) >= 0) {
  610.             if (c == '\n') {
  611.                 if (newline(FFRAND, 1) == FALSE)
  612.                   return FALSE;
  613.                 ++nline;
  614.             } else {
  615.                 if (linsert(1, c) == FALSE)
  616.                   return FALSE;
  617.             }
  618.             ++i;
  619.         }
  620.     }
  621.     lp = curwp->w_linep;            /* Cosmetic adjustment    */
  622.     if (curwp->w_dotp == lp) {        /* if offscreen insert. */
  623.         while (nline-- && lback(lp)!=curbp->b_linep)
  624.             lp = lback(lp);
  625.         curwp->w_linep = lp;        /* Adjust framing.    */
  626.         curwp->w_flag |= WFHARD;
  627.     }
  628.     return TRUE;
  629. }
  630.  
  631. RSIZE getlinenum(bp, lp)
  632. BUFFER *bp;
  633. LINE *lp;
  634. {
  635.   register LINE    *clp;
  636.   register RSIZE nline = 0L;
  637.  
  638.   for (clp = lforw(bp->b_linep); clp; clp = lforw(clp))
  639.     { 
  640.     ++nline;            /* Count this line    */
  641.     if (clp == lp) 
  642.       return(nline);
  643.     }
  644.   return((RSIZE)0);
  645. }
  646. int getrownum(wp, lp)
  647. EWINDOW *wp;
  648. LINE *lp;
  649. {
  650.   register LINE    *clp;
  651.   register int row;
  652.  
  653.   row = wp->w_toprow + 1;        /* Determine row.    */
  654.   clp = wp->w_linep;
  655.   while (clp != lp)
  656.    {
  657.      row++;
  658.      clp = lforw(clp);
  659.      if (clp == wp->w_bufp->b_linep) /* wrapped around, not visible */
  660.         return(-1);
  661.    }
  662.   return(row);
  663. }
  664.  
  665.  
  666. int hardtab(f, n)
  667. int f, n;
  668. {
  669.   ewprintf("Hard Tab");
  670.   if (curbp->b_flag & BFNOTAB)
  671.     return(linsert(4, ' '));
  672.   else
  673.     return(linsert(1, '\t'));
  674. }
  675. /* If active, all TAB keys converted to "indent this line
  676. * so it matches the indent of the last { or }." kinda like GNU 
  677. * formatting features.
  678. *
  679. * Caller sets param 'n' to how many lines to do; 1 is default
  680. * and means do current line.
  681. */
  682. int alignindent(f, n)
  683. int f, n;
  684.   register int i;
  685.   LINE *lp;
  686.  
  687.   if (curbp->b_flag & BFVIEW)
  688.     {
  689.       ttbeep();
  690.       return (FALSE);
  691.     }
  692.  
  693.   if (filetimechanged(curbp))
  694.     return(FALSE);
  695.   clearUndo(curbp);
  696.  
  697.   /* magic time - do something similar to regular old indent, 
  698.   * except watching for formatting chars..
  699.   *
  700.   * clear all whitespace away from beginning of line first
  701.   */
  702.   lp = curwp->w_dotp;
  703.   for (i = 0; i < n; i++)
  704.    {
  705.      int num = indentthisline(lp);
  706. #ifdef INDENTING
  707.      BOOL savetab = usetab;
  708.      usetab = FALSE;
  709.      curwp->w_doto = 0;
  710.      delwhite(0, 1);
  711.      usetab = savetab;
  712. #endif
  713.      performindent(num, lp);
  714.      lp = lforw(lp);
  715.      if (lp = curbp->b_linep)
  716.        break;                /* wrap around */
  717.      curwp->w_dotp = lp;
  718.    }
  719.  
  720.   return (TRUE);
  721. }
  722.  
  723.